import json

from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from py4j.java_gateway import JavaGateway, GatewayParameters
import threading
import time
import sys
path = "E:/pycharmProjects/TiSmart/ti-smart_-agent"
sys.path.insert(0, str(path))
from app.core.config import settings


class RocketMQClient:# 初始化 RocketMQ 客户端，配置连接参数
    def __init__(self, namesrv_addr, producer_group, gateway_host="127.0.0.1", gateway_port=8084):
        self.gateway = JavaGateway(
            gateway_parameters=GatewayParameters(
                address=gateway_host,
                port=gateway_port,
                auto_convert=True,
            )
        )
        self.proxy = self.gateway.entry_point
        self.namesrv_addr = namesrv_addr
        self.producer_group = producer_group
        # 初始化消费者线程对象
        self.consumer_thread = None
        # 初始化消费者运行状态标志
        self.consumer_running = False

    def start_consumer(self, consumer_group, topic):
        """启动消费者"""
        try:
            # 调用 Java 方法启动消费者，传入 Name Server 地址、消费者组名和主题名
            self.proxy.startConsumer(self.namesrv_addr, consumer_group, topic)
            print("✅ 消费者启动成功")
            return True
        except Exception as e:
            print(f"❌ 启动消费者失败: {str(e)}")
            return False

    def consume_message(self, timeout=1):
        """消费消息"""
        try:
            if self.proxy.hasMessage():            # 检查是否有可用消息
                message = self.proxy.getNextMessage() # 获取下一条消息
                return {# 将消息转换为 Python 字典格式并返回
                    "topic": message.getTopic(),
                    "tags": message.getTags(),
                    "body": message.getBody().decode("utf-8"),
                    "msg_id": message.getMsgId(),
                    "born_timestamp": message.getBornTimestamp(),
                    "store_timestamp": message.getStoreTimestamp()
                }
            else:
                time.sleep(timeout)# 如果没有消息，则休眠指定时间
                return None
        except Exception as e:
            print(f"❌ 消费消息失败: {str(e)}")
            return None

    def start_consumer_thread(self, consumer_group, topic, callback):
        """启动消费者线程"""
        if not self.start_consumer(consumer_group, topic):
            return False
        # 设置消费者运行状态为 True
        self.consumer_running = True

        # 定义消费者循环函数
        def consumer_loop():
            while self.consumer_running:# 当消费者运行状态为 True 时持续循环
                message = self.consume_message() # 尝试消费消息
                if message: # 如果成功获取到消息，则调用回调函数处理消息
                    callback(message)

        # 创建消费者线程（设置为守护线程）
        self.consumer_thread = threading.Thread(target=consumer_loop, daemon=True)
        self.consumer_thread.start() # 启动消费者线程
        print("✅ 消费者线程已启动")
        return True

    def stop_consumer_thread(self):
        """停止消费者线程"""
        if self.consumer_thread and self.consumer_running:
            self.consumer_running = False# 设置消费者运行状态为 False，使循环结束
            self.consumer_thread.join(timeout=2)# 等待线程结束（最多等待2秒）
            self.proxy.shutdownConsumer()  # 调用 Java 方法关闭消费者
            print("✅ 消费者线程已停止")

    def shutdown(self):
        """关闭连接"""
        self.stop_consumer_thread() # 停止消费者线程
        self.gateway.shutdownConsumer() # 调用 Java 方法关闭消费者连接
        print("✅ 消费者连接已关闭")


# 配置信息
NAMESRV_ADDR = "127.0.0.1:9876"  # 替换为实际地址
CONSUMER_GROUP = "python_consumer_group"
TOPIC_NAME = "userMessages"


def run_consumer():
    # 创建消费者客户端
    mq_client = RocketMQClient(NAMESRV_ADDR, "")

    # 定义消息处理回调函数
    def message_callback(message):
        print("\n收到消息:")
        print(f"主题: {message['topic']}")
        print(f"标签: {message['tags']}")
        print(f"内容: {message['body']}")
        print(f"消息ID: {message['msg_id']}")
        print(f"生产时间: {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(message['born_timestamp'] / 1000))}")
        print(f"存储时间: {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(message['store_timestamp'] / 1000))}")
        print("大模型判断长期存储...")

        llm = ChatOpenAI(
            base_url=settings.LLM_BASE_URL,
            model=settings.LLM_MODEL,  # deepseek-chat
            temperature=settings.DEFAULT_LLM_TEMPERATURE,  # 0.7
            api_key=settings.LLM_API_KEY,  # sk-cb3aacb93d554d53a0890c5b00d6faa9
            max_tokens=settings.MAX_TOKENS)

        chat_prompt_template = ChatPromptTemplate.from_messages([("user",
        """你的任务是判断用户的输入是否值得被存储为长期记忆。请仔细阅读以下用户输入,并根据给定的标准进行评估:
        用户输入:{context}
        在评估输入时,请考虑以下值得存储为长期记忆的标准，满足其中的一个或多个即可:
        1. 输入包含独特且有价值的信息，如罕见的知识、专业技能要点等。
        2. 输入涉及重要的事件、决策或承诺。
        3. 输入与个人或组织的长期目标、价值观相关。
        4. 输入可能在未来某个时间点对解决问题、做出决策有帮助。
        5. 输入可能可以帮助构建用户画像。
        请按照以下步骤进行评估:
        1. 仔细阅读整个输入内容。
        2. 将输入内容与上述标准逐一对照。
        3. 考虑输入的整体价值和潜在影响。
        4. 形成初步判断。
        5. 再次检查,确保没有遗漏重要细节。
        最后，以严格的JSON格式返回结果，不要包含其他文本，只返回JSON:
        {{
            "thought": "在这里详细分析输入内容是否符合任何值得存储为长期记忆的标准",
            "judgment": "在这里给出'值得'或'不值得'的判断",
            "explanation": "在这里提供详细的解释，说明判断的理由",
            "abstract": "如果值得，则在这里提供摘要以便于存储到数据库中,如果不值得则这里设置为无即可"
        }}""")])
        # res = llm.invoke("这条消息是否需要长期存储，以json格式回答:" + message['body']).content

        chain=chat_prompt_template | llm | StrOutputParser()
        res=chain.invoke({"context":message['body']})
        print(res)
        # 解析JSON结果以便后续处理
        try:
            json_result = json.loads(res)
            print(f"解析后的JSON结果:")
            print(f"  思考过程: {json_result['thought']}")
            print(f"  判断结果: {json_result['judgment']}")
            print(f"  解释说明: {json_result['explanation']}")
            print(f"  摘要: {json_result['abstract']}")

            # 可以在这里添加基于判断结果的后续处理逻辑
            if json_result['judgment'] == '值得':
                print("📌 此消息被标记为值得长期存储")
            else:
                print("🗑️  此消息被标记为不值得长期存储")

        except json.JSONDecodeError:
            print("❌ 大模型返回的结果不是有效的JSON格式")
        except KeyError as e:
            print(f"❌ JSON结果缺少必要字段: {e}")

    # 启动消费者线程并传入消费者组名、主题名和回调函数
    if not mq_client.start_consumer_thread(CONSUMER_GROUP, TOPIC_NAME, message_callback):
        return

    print("\n👂 消费者正在监听消息... (输入'exit'退出)")
    try:
        while True:
            cmd = input()
            if cmd.lower() == "exit":
                print("接收到退出指令...")
                break
    finally:
        mq_client.proxy.shutdownConsumer()
        print("消费者程序已退出")


if __name__ == "__main__":
    run_consumer()
